<script setup>
import {ref, computed, onMounted} from 'vue';
import {ElMessage, ElMessageBox} from "element-plus";

onMounted(() => {
  // 绘制棋盘
  drawGrid();
  // 处理鼠标点击事件
  gobangCanvas.value.addEventListener('click', handleClick);
});

// 计算游戏结束时的提醒消息
const message = computed(() => {
  if (gameEnded.value) {
    return `Game over! ${currentPlayer.value === 'B' ? 'Black' : 'White'} is wins!🥳🎉`;
  }
  return '';
});

// 棋盘画布的引用
const gobangCanvas = ref(null);
// 定义棋盘格尺寸(20*20)
const gridSize = 20;
// 棋盘格单元尺寸(根据画布大小和网格大小计算)
const cellSize = 500 / gridSize;
// 棋盘格线条
const board = ref(Array.from({length: gridSize}, () => Array(gridSize).fill(null))
)
// 当前玩家, 默认为黑棋
const currentPlayer = ref('B');
// 游戏是否结束
const gameEnded = ref(false);
// 落子历史记录，用于撤销上一步落子
const history = ref([]);

// 绘制棋盘网格
const drawGrid = () => {
  const canvas = gobangCanvas.value;
  const context = canvas.getContext('2d');
  context.clearRect(0, 0, canvas.width, canvas.height); // 清除画布
  for (let i = 0; i <= gridSize; i++) {
    context.beginPath(); // 开始绘制路径
    context.moveTo(0, i * cellSize); // 移动到起点
    context.lineTo(canvas.width, i * cellSize); // 绘制到终点
    context.moveTo(i * cellSize, 0); // 移动到起点
    context.lineTo(i * cellSize, canvas.height); // 绘制到终点
    context.strokeStyle = '#000000'; // 线条颜色
    context.stroke();
  }

};


// 在指定位置绘制棋子
const drawStone = (x, y, color) => {
  const canvas = gobangCanvas.value;
  const context = canvas.getContext('2d');
  context.beginPath(); // 开始绘制路径
  context.arc(x * cellSize + cellSize / 2, y * cellSize + cellSize / 2, cellSize / 2 - 5, 0, 2 * Math.PI); // 绘制圆形
  context.fillStyle = color; // 填充颜色
  context.fill(); // 填充路径
  context.strokeStyle = '#000000'; // 线条颜色
  context.lineWidth = 2; // 线条宽度
  context.stroke(); // 绘制路径
}

// 在指定位置落子
const placeStone = (row, col) => {
  // 如果该位置已有棋子或游戏结束，则不允许落子
  if (board.value[row][col] || gameEnded.value)
    return ElMessage({
      showClose: true,
      message: '该位置已有棋子, 请重新选择位置!',
      type: 'warning'
    });

  // 记录落子历史，更新棋盘状态
  history.value.push({row, col, player: currentPlayer.value});
  board.value[row][col] = currentPlayer.value;
  // 绘制棋子
  drawStone(col, row, currentPlayer.value === 'B' ? 'black' : 'white'); //
  // 检查是否获胜
  if (checkWin(row, col)) {
    gameEnded.value = true;
    ElMessage.success(`Player ${currentPlayer.value} wins!`);
  } else {
    // 切换玩家
    currentPlayer.value = currentPlayer.value === 'B' ? 'W' : 'B';
  }
}

// 检查当前玩家是否获胜
const checkWin = (row, col) => {
  const directions = [
    {dx: 1, dy: 0}, // 横向
    {dx: 0, dy: 1}, // 纵向
    {dx: 1, dy: 1}, // 斜交 /
    {dx: -1, dy: 1} // 斜交 \
  ];

  // 遍历每一个方向，检查横向、纵向、斜向是否有五个连续的同色棋子
  for (const {dx, dy} of directions) {
    let count = 1;
    // 正方向检查
    for (let i = 1; i < 5; i++) {
      const newRow = row + dx * i;
      const newCol = col + dy * i;
      if (
          newRow >= 0 && newRow < gridSize &&
          newCol >= 0 && newCol < gridSize &&
          board.value[newRow][newCol] === currentPlayer.value
      ) {
        count++;
      } else {
        break;
      }
    }
    // 反方向检查
    for (let i = 1; i < 5; i++) {
      const newRow = row - dx * i;
      const newCol = col - dy * i;
      if (
          newRow >= 0 && newRow < gridSize &&
          newCol >= 0 && newCol < gridSize &&
          board.value[newRow][newCol] === currentPlayer.value
      ) {
        count++;
      } else {
        break;
      }
    }
    // 如果连续相同棋子数量达到 5，则返回 true（获胜）
    if (count >= 5) {
      return true;
    }
  }
  return false;
};

// 处理鼠标点击事件
const handleClick = (event) => {
  // 如果游戏已经结束，则不允许落子
  if (gameEnded.value) {
    ElMessageBox.alert('游戏已经结束，请重新开始!', '提示', {
      type: 'warning',
      confirmButtonText: '确定',
      callback: () => {
        restartGame();
      }
    });
    return;
  }
  // 计算点击位置对应的网格坐标
  const rect = gobangCanvas.value.getBoundingClientRect();
  const x = event.clientX - rect.left;
  const y = event.clientY - rect.top;
  // 转换为网格坐标
  const col = Math.floor(x / cellSize);
  const row = Math.floor(y / cellSize);
  // 对应位置落子
  placeStone(row, col);
};

// 重新开始游戏
const restartGame = () => {
  board.value = Array.from({length: gridSize}, () => Array(gridSize).fill(null)); // 清空棋盘
  currentPlayer.value = 'B';
  gameEnded.value = false;
  history.value = [];
  drawGrid();
};

// 撤销上一步落子
const undoMove = () => {
  if (history.value.length === 0 || gameEnded.value)
    return ElMessage.warning('无可撤销棋子，请重新开始!');
  const lastMove = history.value.pop();   // 获取上一步落子记录
  drawStone(lastMove.col, lastMove.row, null); // 重绘上一步的棋子
  board.value[lastMove.row][lastMove.col] = null; // 更新棋盘状态
  currentPlayer.value = lastMove.player; // 切换回上一步的玩家
  gameEnded.value = false;
  drawGrid();
  redrawHistory();
};

// 重绘历史记录中移动的棋子
const redrawHistory = () => {
  history.value.forEach(move => {
    drawStone(move.col, move.row, move.player === 'B' ? 'black' : 'white');
  });
};


</script>

<template>
  <div class="message" v-if="message">{{ message }}</div>

  <div class="game-view">
    <canvas ref="gobangCanvas" width="500" height="500"></canvas>
    <!-- 底部按钮栏 -->
    <div class="controls">
      <el-button type="primary" plain @click="restartGame">🔁 New Game</el-button>
      <el-button type="primary" plain @click="undoMove">Undo Move ↩️</el-button>
    </div>
  </div>
</template>

<style scoped>
.message {
  color: #666565;
  background: linear-gradient(to right, #88aff3, #39f3d7, #fae56b, #90ee90, #00ced1);
  font-family: "Arial, sans-serif", sans-serif;
  font-size: 32px;
  font-weight: bold;
  white-space: nowrap;
  border-radius: 10px;
  padding: 15px 20px;
  margin-bottom: 30px;
  box-shadow: 5px 5px 0 #f19494;
  cursor: pointer;
  transition: transform 0.1s ease-in-out;
}

.game-view {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

canvas {
  background-color: rgba(182, 83, 243, 0.68);
  box-shadow: 0 4px 8px rgb(31, 185, 246);
  cursor: pointer;
  opacity: 0.7;
  border-radius: 10px;
}

.controls {
  margin-top: 20px;
}

.el-button {
  padding: 20px;
  font-size: 22px;
  font-weight: bold;
  border-radius: 10px;
  background-color: #a186be;
  color: #f5f5f5;
  box-shadow: 5px 5px 0 #55acee;
  margin: 10px;
  cursor: pointer;
}
.el-button:hover {
  transform: scale(1.1);
  background-color: #ffffff;
  color: #a186be;
}


</style>